#include "nw_client.h"
#include "nw_protocol.h"
#include "nw_costmode.h"
#include "nw_client_pal.h"
#include "platform.h"
#include "sm4.h"
#include "log.h"
#include "string.h"
#include "utility.h"
#include "nw_order.h"

#define TIMER_INTETVAL_MS 50

#define MAX_NW_INCIEDENT_DATA_LEN (300)//事件数据最大长度
#define MAX_NW_INCIDEENT_DATA_SUM (3U)//处理时间最大长度

enum{
	E_RECORDFROM_FILE= 0,//从文件中读取记录
	E_RECORDFROM_ORDER,//从订单中读取记录
};
typedef void (*typecmddeal) (uint8 *,uint32);

struct t_typecmddeal
{
  uint8 type;
  typecmddeal deal;
};

struct nwcmditem
{
    uint32 len;
    uint8 data[MAX_NW_INCIEDENT_DATA_LEN];
};
struct t_nwcmdinfo
{
    uint32 head;
    uint32 tail;
    struct nwcmditem nwcmditem_list[MAX_NW_INCIDEENT_DATA_SUM];
};

struct t_nwparams//需要保存的参数
{
   uint8 paras_ver;//本参数的版本号
   uint8 sdk_version[4];//SDK 版本 软件版本号
   uint8 dev_type;//设备类型//交流 直流 交直流一体
   uint8 gun_cnt;//枪数量
   uint8 devnum[16];//充电桩编码
   uint8 costmode_id[8];//计费模型id
   uint8 chargemode;  //充电模式 位表示法
   uint8 serveip[20];//连接服务器ip
	 uint32 port;//服务器端口
   struct t_nw_promsg nwpromsg;//南网协议的一些信息
};

typedef void (*state_init) (void *);
typedef void (*state_poll) (void *);
struct t_nw_state
{
	uint8 state;
	state_poll init;
	state_init poll; 
};

struct t_gunmsg
{
    uint8 gunno;
  	struct t_nw_state gun_state;//设备状态机;
    struct ClientUserGunInfo *user_gun_info; //设备端同步过来的枪参数
    struct ClientUserBmsInfo *user_bms_info; //设备端同步过来的bms参数
    uint16 interval_datarep;//实时监测数据上报时间间隔  单位 分钟 默认为5分钟
    uint16 interval_minrep;//变化数据上传最小时间间隔  单位秒  默认60秒
    uint16 interval_keeplive;//心跳周期间隔  单位秒 默认15秒
    struct t_ac_devyx devyx;//设备的遥信数据
    struct t_ac_devyc_halfword devyc;//遥测数据等于两个字节的
    struct t_ac_devyc_morehalfword devycmorehalfword;//遥测数据大于两个字节的
    uint32 clipoll_cnt;//轮询计数
    uint32 datarep_cnt;//实时监控数据上报时间间隔计数
    uint32 minrep_cnt;//变化数据最小上传时间间隔计数
	  uint32 lastpower;//上次电量 精确到到0.1
	  struct t_pal_alarm alarmmsg;//需要缓存的告警信息	 
    struct t_cli_costmode guncodemode;//计费模型信息
	  struct t_nw_order order;//订单信息
	  uint32 keepliverecv;//心跳包接收状态
	  uint32 keeplivecnt;//心跳包计数
};


struct t_nw_client
{
   uint8 proinit_sta;//是否发送协议标识帧标志位
   uint8 startdtack_sta;//允许数据传输应答状态
   uint8 allcall_sta;//总召完成标志位
   uint8 timesyn_sta;//时间同步状态
	 uint8 devpara_sta;//设备参数下发状态
   uint8 costmode_sta;//计费模型下发状态
   uint8 signin_sta;//签到状态
   uint32 relogin_cnt;//重连次数

	 struct SocketApi *socketapi;//网络适配器
   pal_socket_t socket;
	
   struct t_nwparams nwparams;//需要保存的参数 
   struct t_gunmsg *gunmsg;//枪的一些信息
	
};
static os_mutex_t nwpro_mutex = NULL;
static struct t_nw_client nwclient; 

#if 0
static uint8 push_cmdlist(struct t_nwcmdinfo *info,const uint8 *buf,uint32 len)
{
    if(info->head == ((info->tail +1)%MAX_NW_INCIDEENT_DATA_SUM))//队列已满
    {
        return 0;
    }

    if(len >=MAX_NW_INCIEDENT_DATA_LEN)
    {
        return 0;
    }
    uint32 pos = info->tail;
    memset((info->nwcmditem_list+pos)->data,0,MAX_NW_INCIEDENT_DATA_LEN);
    memcpy((info->nwcmditem_list+pos)->data,buf,len);
    (info->nwcmditem_list+pos)->len = len;
    info->tail = (info->tail+1)%MAX_NW_INCIDEENT_DATA_SUM;
    return 1;
}

static uint8 pop_cmdlist(struct t_nwcmdinfo *info,uint8 *buf,uint32 *len)
{
    if(info->head == info->tail)//队列为空
    {
       return 0;
    }
    uint32 pos = info->head;

    *len = (info->nwcmditem_list+pos)->len;
    memcpy(buf,(info->nwcmditem_list+pos)->data,*len);

    info->head = (info->head+1)%MAX_NW_INCIDEENT_DATA_SUM;
    return 1;
}
#endif
static uint8 change_stateto(uint32 gunno,uint8 state);
static void state_alarm_poll(void *msg)
{
	struct t_gunmsg *pgunmsg =  (struct t_gunmsg *)msg;
  if(!ishave_alarm(&pgunmsg->alarmmsg)){
	   change_stateto(pgunmsg->gunno,E_NW_STATE_IDLE);
	}
}
static void state_idle_poll(void *msg)
{
	struct t_gunmsg *pgunmsg =  (struct t_gunmsg *)msg;
	if(pgunmsg->devyx.connect_state){//枪已经连接
		 change_stateto(pgunmsg->gunno,E_NW_STATE_ONGUN);
	}
	if(ishave_alarm(&pgunmsg->alarmmsg)){
	   change_stateto(pgunmsg->gunno,E_NW_STATE_ALARM);
	}
}
static void state_work_poll(void *msg)
{
	struct t_gunmsg *pgunmsg =  (struct t_gunmsg *)msg;
	
	uint32 power =pal_gettotal_actually_power(pgunmsg->user_gun_info);
	order_updatepower(&pgunmsg->order,power);
}
static void state_finish_poll(void *msg)
{
	 
}
static void state_ongun_poll(void *msg)
{
	struct t_gunmsg *pgunmsg =  (struct t_gunmsg *)msg;
	
  if(ishave_alarm(&pgunmsg->alarmmsg)){
	   change_stateto(pgunmsg->gunno,E_NW_STATE_ALARM);
	}
	if(!pgunmsg->devyx.connect_state){//枪没有连接
		 change_stateto(pgunmsg->gunno,E_NW_STATE_IDLE);
	}
}
static void state_alarm_init(void *msg)
{
	
}
static void state_idle_init(void *msg)
{
	struct t_gunmsg *pgunmsg =  (struct t_gunmsg *)msg;
	reset_order(&pgunmsg->order);
}
static void state_work_init(void *msg)
{
	 
}
static void state_finish_init(void *msg)
{
	 
}
static void state_ongun_init(void *msg)
{
	 
}

static struct t_nw_state nwstate_buf[] = 
{	
	{E_NW_STATE_ALARM,state_alarm_init,state_alarm_poll}, 
	{E_NW_STATE_IDLE,state_idle_init,state_idle_poll}, 
	{E_NW_STATE_WORK,state_work_init,state_work_poll},
	{E_NW_STATE_FINISH,state_finish_init,state_finish_poll},
	{E_NW_STATE_ONGUN,state_ongun_init,state_ongun_poll},
};

struct t_nw_state *get_state_msg(uint8 state)
{
	uint32 len = sizeof(nwstate_buf)/sizeof(struct t_nw_state);
	uint32 i = 0;
	for(;i<len;i++)
	{
		 if(state == nwstate_buf[i].state)
		 {
			   return nwstate_buf+i;
		 }
	}
	return 0;
}
static uint8 get_gunstate(struct t_gunmsg *gunmsg)
{
	return gunmsg->gun_state.state;
}
static uint8 change_stateto(uint32 gunno,uint8 state)
{
	  struct t_gunmsg *gunmsg = nwclient.gunmsg+gunno;
	  struct t_nw_state *ptmpstate = get_state_msg(state);
	  if(!ptmpstate) 
		{
			 return 0;
		}
		gunmsg->gun_state.state =  ptmpstate->state;
		gunmsg->gun_state.init = ptmpstate->init;
		gunmsg->gun_state.poll = ptmpstate->poll;	
		
  	gunmsg->gun_state.init((void *)gunmsg);
		return 1;
}

static void gunmsg_init(struct t_gunmsg *gunmsg,uint32 guncnt)
{
	  memset((uint8 *)gunmsg,0,sizeof(struct t_gunmsg)*guncnt);
    struct ClientUserGunInfo *pguninfo = pal_get_user_client_gun_data();
    struct ClientUserBmsInfo *pbmsinfo =  pal_get_user_client_bms_data();

    uint32 i = 0;
    for(i = 0;i<guncnt;i++)
    {
			 (gunmsg+i)->gunno = i;
				change_stateto(i,E_NW_STATE_IDLE);
       (gunmsg+i)->interval_datarep = 5;//实时监测数据上报时间间隔  单位 分钟 默认为5分钟
       (gunmsg+i)->interval_minrep = 60;//变化数据上传最小时间间隔  单位秒  默认60秒
       (gunmsg+i)->interval_keeplive = 15;//心跳周期间隔  单位秒 默认15秒
       (gunmsg+i)->user_gun_info = pguninfo+i;
       (gunmsg+i)->user_bms_info = pbmsinfo+i;
			 (gunmsg+i)->keepliverecv = 1;
			
			 (gunmsg+i)->guncodemode.gunno = i;
			
			  costmode_init(&(gunmsg+i)->guncodemode);
    }
}
static void nw_param_init(struct t_nwparams *params)
{
   params->gun_cnt = 1;//枪数量

   //uint8 devnum[8] = {0x44,0x03,0x10,0x00,0x39,0x00,0x20,0x01};//充电桩编码
	 //uint8 devnum[8] = {0x44,0x03,0x10,0x00,0x39,0x99,0x88,0x09};//充电桩编码
	 uint8 devnum[8] = {0x01,0x02,0x03,0x18,0x10,0x03,0x00,0x50};//充电桩编码
	
   memcpy(params->devnum,devnum,sizeof(devnum));

   params->chargemode =0x0f;  //充电模式 位表示法

   uint8 sm4[16] ={'S','Z','E','V','C','S','2','0','1','6','0','0','0','0','0','0'};
   memcpy(params->nwpromsg.sm4,sm4,16);

   params->nwpromsg.apcihead = 0x68;//acpi信息头部
   params->nwpromsg.publicaddr = 0x0001;//公共地址0x0001;

	 pal_getserverip(params->serveip);
	 params->port = pal_getserverport();
	 
   nwpro_init(&params->nwpromsg);
}
#if 0
static void get_nw_devnum(uint8 *devnum)
{
	memcpy(devnum,nwclient.nwparams.devnum,8);
}
#endif
static void client_send(uint8 *data,uint32 len)
{
   // 这里要加信号量
  if(!nwclient.socketapi || 
		 nwclient.socket <=0){
		  return ;
	}
	os_mutex_lock(&nwpro_mutex);  
	
	printf("send<<");
	for(uint32 i = 0;i<len;i++){
		printf("%02x",*(data+i));
	}
  if(len > 7){
     uint8 out[PRO_MAX_DATA] = {0};
     sm4_context ctx;

     sm4_setkey_dec(&ctx, nwclient.nwparams.nwpromsg.sm4);
     sm4_crypt_ecb(&ctx, 0, len-13, data+13, out);
		 
		 printf("      dissm4:");
		 for(uint32 i = 0;i<len;i++){
			 printf("%02x",*(out+i));
		 }
  }
	printf("\r\n");
  nwclient.socketapi->send(nwclient.socket,data,len,0);
  os_mutex_unlock(&nwpro_mutex); 
}

static uint8 cli_startcharge(uint8 gunno,uint8 start_way,void *arg,uint8 *failreason)
{	
	struct t_gunmsg *gunmsg = nwclient.gunmsg+gunno;
	if(E_NW_STATE_IDLE == get_gunstate(gunmsg)){
		 *failreason = E_START_FAIL_DEVNOTCONN;
		 return E_START_FLAG_FAIL;
	}
	else if(E_NW_STATE_WORK == get_gunstate(gunmsg)){
		 *failreason = E_START_FAIL_CHARGING;
		 return E_START_FLAG_FAIL;
	}
	else if(E_NW_STATE_ALARM == get_gunstate(gunmsg)){
		 *failreason = E_START_FAIL_DEVALARM;
		 return E_START_FLAG_FAIL;
	}
	//更新计费模型
	costmode_change(&gunmsg->guncodemode);
	//初始化订单信息
	init_order(&gunmsg->order,&gunmsg->guncodemode,start_way,arg);
	
	change_stateto(gunno,E_NW_STATE_WORK);
  pal_callback_startcharge(gunno);
  return E_START_FLAG_SUCC;
}

//E_ENDFLAG_SUCC = 0,
//E_ENDFLAG_FAIL ,.
void send_remotestop_ack(uint32 gunno,uint8 ret);//发送停止充电应答
void send_chargerecord(uint32 gunno,uint8 recordtype);//上报充电记录


static uint8 cli_stopcharge(uint8 gunno,uint8 stopway,void *arg)
{
	uint8 ret = E_ENDFLAG_SUCC;
	struct t_gunmsg *gunmsg = nwclient.gunmsg+gunno;
	
	if (stopway == E_END_BY_REMOTE){//如果是远程结束的
  	 struct t_down_remote_stop *stoparg = (struct t_down_remote_stop *)arg;	
	   uint8 userid[8] = {0};
   	 get_order_userid(&gunmsg->order,userid);
	   if(memcmp(userid,stoparg->stop,8) != 0){//订单号不一样
		   ret = E_STOPREASON_USERID_ERR | E_ENDFLAG_FAIL;
	   }
	   if(get_gunstate(gunmsg) != E_NW_STATE_WORK){//没在工作中
		   ret = E_STOPREASON_NOCHARGE_ERR | E_ENDFLAG_FAIL;
	   }
	   
      send_remotestop_ack(gunno,ret);//发送停止应答
		  if(ret != E_ENDFLAG_SUCC){
		  return 0;
		 }
	}
  order_set_endreason(&gunmsg->order,stopway);//设置结束原因
	send_chargerecord(gunno,E_RECORDFROM_ORDER);//发送充电记录
	
	pal_callback_stopcharge(gunno);	//设备的结束充电
	change_stateto(gunno,E_NW_STATE_IDLE);//转为空闲状态
	return 0;
}
static uint8 sync_acyx(struct t_gunmsg *gunmsg)
{
  if(!gunmsg)
  {
      return 0;
  }
  struct t_ac_devyx tmpyx = {0};
  memcpy((uint8 *)&tmpyx,(uint8 *)&(gunmsg->devyx),sizeof(tmpyx));
	
  gunmsg->devyx.connect_state = pal_getconnect_sta(gunmsg->user_gun_info);//连接确认开关状态
  gunmsg->devyx.ac_input_v_overalarm = pal_getac_input_v_overalarm(&gunmsg->alarmmsg);//输入电压过压告警
  gunmsg->devyx.ac_input_v_lowlarm = pal_getac_input_v_lowlarm(&gunmsg->alarmmsg);
  gunmsg->devyx.current_overalarm =  pal_getcurrent_overalarm(&gunmsg->alarmmsg);
  gunmsg->devyx.output_relay_state = pal_getoutput_relay_state(gunmsg->user_gun_info);
  gunmsg->devyx.temp_over_pro = pal_gettemp_over_pro(&gunmsg->alarmmsg);
  gunmsg->devyx.short_circuit_pro = pal_getshort_circuit_pro(&gunmsg->alarmmsg);
  gunmsg->devyx.leakage_pro = pal_getleakage_pro(&gunmsg->alarmmsg);
  gunmsg->devyx.stopbutton_trigger = pal_getstopbutton_trigger(&gunmsg->alarmmsg);

  if(!memcmp((uint8 *)&tmpyx,(uint8 *)&gunmsg->devyx,sizeof(tmpyx)))//说明状态没有更改
  {
     return 0;
  }
  return 1;
}
static uint8 sync_acyc(struct t_gunmsg *gunmsg)
{
	  uint8 ret = 0;
    if(!gunmsg)
    {
        return 0;
    }
		if(gunmsg->devyc.work_state != gunmsg->gun_state.state)
		{		
			 ret  = 1;
		}
	  gunmsg->devyc.work_state = gunmsg->gun_state.state;
    gunmsg->devyc.output_voltage = pal_getoutput_voltage(gunmsg->user_gun_info);
    gunmsg->devyc.output_current = pal_getoutput_current(gunmsg->user_gun_info);
    gunmsg->devyc.voltage_A = pal_getvoltage_A(gunmsg->user_gun_info);
    gunmsg->devyc.voltage_B = pal_getvoltage_B(gunmsg->user_gun_info);
    gunmsg->devyc.voltage_C = pal_getvoltage_C(gunmsg->user_gun_info);
    gunmsg->devyc.current_A = pal_getcurrent_A(gunmsg->user_gun_info);
    gunmsg->devyc.current_B = pal_getcurrent_B(gunmsg->user_gun_info);
    gunmsg->devyc.currenr_C = pal_getcurrenr_C(gunmsg->user_gun_info);
    return ret;
}
static uint8 sync_acyc_morehalfword(struct t_gunmsg *gunmsg)
{
    if(!gunmsg)
    {
        return 0;
    }
		uint32 getpower = pal_gettotal_actually_power(gunmsg->user_gun_info)/10;
    gunmsg->devycmorehalfword.total_actually_power  = getpower;
    gunmsg->devycmorehalfword.elecvalue_outside = pal_getelecvalue_outside(gunmsg->user_gun_info);
		
		if(getpower!= gunmsg->lastpower)
		{
			gunmsg->lastpower = getpower;
			return 1;	
		}
    return 0;
}
static uint8 cli_bilrecord_fromrecord(uint32 gunno,struct t_up_chargerecord *chargerecord)
{
   uint8 ret = pal_read_bill((uint8 *)chargerecord);
	 if(!ret){//没有记录可以读了
		  return 0;
	 }
	 uint32 guncnt = nwclient.nwparams.gun_cnt;
	 struct t_gunmsg *pgun= nwclient.gunmsg;
	 for(uint32 i = 0;i<guncnt;i++){
		 if(chargerecord->gunno == i){//记录里是当前枪
		      if(get_gunstate(pgun) != E_NW_STATE_WORK){//不是充电状态
						return 1;//返回1记录可以上传
					}
				  uint8 tradenum[16] = {0};
			    get_order_tradeno(&pgun->order,tradenum);
			    if(memcmp(tradenum,chargerecord->trade_num,16) != 0){//订单号不相等
						  return 1; 
					}
		      return 0;
		 }
	}
	return 0;
}
static uint8 cli_bilrecord_fromorder(uint32 gunno,struct t_up_chargerecord *chargerecord)//冲订单中读取充电记录
{
	struct t_gunmsg *pgunmsg = nwclient.gunmsg+gunno;
	
	memcpy(chargerecord->devnum,nwclient.nwparams.devnum,8);
	chargerecord->gunno = gunno;
	get_order_tradeno(&pgunmsg->order,chargerecord->trade_num);
	get_order_cardno(&pgunmsg->order,chargerecord->paycardno);
	get_order_cardno(&pgunmsg->order,chargerecord->hardcardno);
  chargerecord->time_sharing_cal_flag = get_order_sharetime_flag(&pgunmsg->order);
	get_order_begintime(&pgunmsg->order,chargerecord->begintime);
  get_order_endtime(&pgunmsg->order,chargerecord->endtime);
	
	chargerecord->tip_start_value = 0;
	chargerecord->tip_stop_value = 0;
	chargerecord->peak_start_value = 0;
	chargerecord->peak_stop_value = 0;
	chargerecord->normal_start_value = 0;
	chargerecord->normal_stop_value = 0;
	chargerecord->valley_start_value = 0;
	chargerecord->valley_stop_value = 0;
	
	chargerecord->caltype = get_order_caltype(&pgunmsg->order);
	
	chargerecord->total_start_value = 0;
	chargerecord->total_stop_value = 0;
	
	chargerecord->tip_pcs = get_order_time_pcs(&pgunmsg->order,E_COSTMODE_TIP);
	chargerecord->tip_power =  get_order_time_power(&pgunmsg->order,E_COSTMODE_TIP);
	chargerecord->tip_money = get_order_time_eleccost(&pgunmsg->order,E_COSTMODE_TIP);
	
	chargerecord->peak_pcs = get_order_time_pcs(&pgunmsg->order,E_COSTMODE_PEAK);
	chargerecord->peak_power =  get_order_time_power(&pgunmsg->order,E_COSTMODE_PEAK);
	chargerecord->peak_money = get_order_time_eleccost(&pgunmsg->order,E_COSTMODE_PEAK);
	
	chargerecord->normal_pcs = get_order_time_pcs(&pgunmsg->order,E_COSTMODE_NORMAL);
	chargerecord->normal_power =  get_order_time_power(&pgunmsg->order,E_COSTMODE_NORMAL);
	chargerecord->normal_money = get_order_time_eleccost(&pgunmsg->order,E_COSTMODE_NORMAL);
	
	chargerecord->valley_pcs = get_order_time_pcs(&pgunmsg->order,E_COSTMODE_VALLEY);
	chargerecord->valley_power =  get_order_time_power(&pgunmsg->order,E_COSTMODE_VALLEY);
	chargerecord->valley_money = get_order_time_eleccost(&pgunmsg->order,E_COSTMODE_VALLEY);
	
	chargerecord->total_power = get_order_total_power(&pgunmsg->order);
	
	chargerecord->business_type = get_order_business_type(&pgunmsg->order);
	chargerecord->money_afterpay = get_order_money_afterpay(&pgunmsg->order);
	
	chargerecord->consume_pcs  = get_order_consume_pcs(&pgunmsg->order);//获取消费单价
  chargerecord->consume_money  = get_order_consume_money(&pgunmsg->order);//获取消费金额
	
	memset(chargerecord->carvin,0,17);

	chargerecord->trade_flag = 0xff;
  memset(chargerecord->client_terminal_num,0xff,6);
	chargerecord->money_beforepay = get_order_user_remain(&pgunmsg->order);

	chargerecord->wallet_trade_serialnum = 0xff;
	chargerecord->trade_money = 0xff;
	
	get_order_endtime(&pgunmsg->order,chargerecord->trade_date);
	chargerecord->fake_num = 0xff;
	chargerecord->trade_type_flag = 0xff;
	chargerecord->tac = 0xff;
	chargerecord->key_ver = 0xff;
	chargerecord->terminal_trade_serialnum = 0xff;
	
	chargerecord->server_pcs = get_order_time_servecost(&pgunmsg->order,E_COSTMODE_TIP);
	chargerecord->server_cost = get_order_total_servercost(&pgunmsg->order);
	
	chargerecord->reserve_pcs = get_order_reserve_pcs(&pgunmsg->order,E_COSTMODE_TIP);
	chargerecord->reserve_cost = get_order_total_reservecost(&pgunmsg->order);
	
  chargerecord->position_pcs = get_order_position_pcs(&pgunmsg->order,E_COSTMODE_TIP);
	chargerecord->position_cost = get_order_total_positioncost(&pgunmsg->order);
	
	chargerecord->total_eleccost = get_order_total_eleccost(&pgunmsg->order);
	get_order_costmode_id(&pgunmsg->order,chargerecord->costmodeid);
	chargerecord->total_cost = get_order_totalcost(&pgunmsg->order);
  chargerecord->endreason =  order_get_endreason(&pgunmsg->order);
	get_order_userid(&pgunmsg->order,chargerecord->userid);

	chargerecord->tip_server_pcs = get_order_time_servepcs(&pgunmsg->order,E_COSTMODE_TIP);
	chargerecord->tip_server_cost = get_order_time_servecost(&pgunmsg->order,E_COSTMODE_TIP);
	
	chargerecord->peak_server_pcs = get_order_time_servepcs(&pgunmsg->order,E_COSTMODE_PEAK);
	chargerecord->peak_server_cost = get_order_time_servecost(&pgunmsg->order,E_COSTMODE_PEAK);
	
	chargerecord->normal_server_pcs = get_order_time_servepcs(&pgunmsg->order,E_COSTMODE_NORMAL);
	chargerecord->normal_server_cost = get_order_time_servecost(&pgunmsg->order,E_COSTMODE_NORMAL);
	
	chargerecord->valley_server_pcs = get_order_time_servepcs(&pgunmsg->order,E_COSTMODE_VALLEY);
	chargerecord->valley_server_cost = get_order_time_servecost(&pgunmsg->order,E_COSTMODE_VALLEY);
	
	get_order_orderno(&pgunmsg->order,chargerecord->orderno);
	return 1;
}
static void send_chargerecord(uint32 gunno,uint8 recordtype)//上报充电记录
{
	struct t_up_chargerecord chargerecord;
	memset((uint8 *)&chargerecord,0,sizeof(chargerecord));
	
	uint8 ret = 0;
	if(E_RECORDFROM_FILE == recordtype){	
		ret = cli_bilrecord_fromrecord(gunno,&chargerecord);
		
	}else if(E_RECORDFROM_ORDER == recordtype){
	  ret = cli_bilrecord_fromorder(gunno,&chargerecord);
	}	
	if(ret){
	  uint8 data[PRO_MAX_DATA] = {0};
	  uint32 len = 0;
	
	  probill_chargerecord(&chargerecord,data,&len);
    client_send(data,len);
  }else{
		printf("nothing record to send\r\n");
	}
}

static void clientbill_initmsg(const struct t_nwparams *params,uint8 *data,uint32 *len)//组装协议标识帧
{    
    struct t_nw_pro_init msg;
    memset((uint8 *)&msg,0,sizeof(msg));
	
    msg.flag = 0xff;//协议启动标识帧
    msg.ver = 0x02;//协议版本
    memcpy(msg.costmode_id,params->costmode_id,8);//计费模型id;
    memcpy(msg.devnum,params->devnum,8);//设备编码;
    msg.gun_cnt = params->gun_cnt;//枪口数量
    msg.chargemode = params->chargemode;//充电模式
    msg.addr = (msg.devnum[1]<<8)+msg.devnum[0];//站地址;

    probill_proinitmsg(&msg,data,len);//协议部分构件
}

static void send_proinit()//发送协议初始化帧
{
    uint8 data[PRO_MAX_DATA] = {0};
    uint32 len = 0;

    memset(data,0,sizeof(data));

    clientbill_initmsg(&nwclient.nwparams,data,&len);
    client_send(data,len);
}
static void send_startdt_req()//使用u帧应答启动数据传输
{
    uint8 data[PRO_MAX_DATA] = {0};
    uint32 len = 0;

    probill_startdtmsg(data,&len);
    client_send(data,len);
}
static void send_allcall_confirm()//总召确认
{
    uint8 data[PRO_MAX_DATA] = {0};
    uint32 len = 0;

    probill_allcall(E_CAUSE_ACT_CON,data,&len);
    client_send(data,len);
}
static void send_allcallack_1()//响应总召
{
    if(!nwclient.gunmsg)
    {
         return ;
    }
    uint8 data[PRO_MAX_DATA] = {0};
    uint32 len = 0;

    probill_acyx(E_CAUSE_CALL_ACK,0, &(nwclient.gunmsg+0)->devyx, data, &len);
    client_send(data,len);
}
static void send_allcallack_11()//响应总召
{
    if(!nwclient.gunmsg)
    {
         return ;
    }
    uint8 data[PRO_MAX_DATA] = {0};
    uint32 len = 0;


    probill_acyc_halfword(E_CAUSE_CALL_ACK,0,&(nwclient.gunmsg+0)->devyc,data,&len);
    client_send(data,len);
}
static void send_allcallack_132()//响应总召
{
    if(!nwclient.gunmsg)
    {
         return ;
    }
    uint8 data[PRO_MAX_DATA] = {0};
    uint32 len = 0;

    probill_acyc_morehalfword(E_CAUSE_CALL_ACK,0,&(nwclient.gunmsg+0)->devycmorehalfword,data,&len);
    client_send(data,len);
}
static void send_allcall_end()//总召结束
{
    uint8 data[PRO_MAX_DATA] = {0};
    uint32 len = 0;

    probill_allcall(E_CAUSE_ACT_END,data,&len);
    client_send(data,len);
}
static void send_timesync_ack(uint8 *time)//时间同步应答
{
    uint8 data[PRO_MAX_DATA] = {0};
    uint32 len = 0;

    probill_timesync_ack(E_CAUSE_ACT_CON,time,data,&len);
    client_send(data,len);
}
static void send_deaparaset_ack(uint8 gunno,uint8 flag)//发送设备参数设置应答
{
  struct t_up_reportpara_set_ack ack = {0};
  memcpy(ack.devnum,nwclient.nwparams.devnum,8);
  ack.gunno = gunno;
  ack.flag = flag;

  uint8 data[PRO_MAX_DATA] ={0};
  uint32 len = 0;
  probill_devparaset_ack(&ack,data,&len);
  client_send(data,len);

}
#if 0
static void send_costmode_req(uint8 gunno)//请求发下计费模型
{
    struct t_up_require_costmode ack = {0};
    memcpy(ack.devnum,nwclient.nwparams.devnum,8);
    ack.gunno = gunno;

    uint8 data[PRO_MAX_DATA] ={0};
    uint32 len = 0;
    probill_costmode_req(&ack,data,&len);
    client_send(data,len);
}
#endif
static void send_remotestart_ack(uint8 gunno,uint8 flag,uint8 fail_reason)
{
	  struct t_up_remote_start_ack ack = {0};
	  memset((uint8 *)&ack,0,sizeof(struct t_up_remote_start_ack));
		
		struct t_gunmsg *pgunmsg = nwclient.gunmsg+gunno;
			
		memcpy(ack.devnum,nwclient.nwparams.devnum,8);
		ack.gunno = gunno;
	  get_order_tradeno(&pgunmsg->order,ack.trade_num);
	  get_costmode(&pgunmsg->guncodemode,ack.costmode);
    ack.startway = get_order_startway(&pgunmsg->order);
	  ack.result = flag;
  	ack.reason = fail_reason;
	  ack.max_total_v = pgunmsg->user_bms_info->bcp_total_voltage;
	  ack.max_total_i =  pgunmsg->user_bms_info->bcp_max_current;
	  ack.battey_total_power =  pgunmsg->user_bms_info->bcp_max_power;
	  ack.max_temp =  pgunmsg->user_bms_info->bcp_max_temperature;
    ack.single_battery_max_v = pgunmsg->user_bms_info->bcp_max_voltage;
	  ack.batterynow_v = pgunmsg->user_bms_info->bcp_battery_soc_current_voltage;
		
		if(ack.startway == E_START_BYCARD){
			get_order_cardno(&pgunmsg->order,ack.userid);	
		}
		else{
		  get_order_userid(&pgunmsg->order,ack.userid);	
		}
		
		uint8 data[PRO_MAX_DATA] = {0};
		uint32 len = 0;
		probill_remotestart_ack(&ack,data,&len);
		
   	client_send(data,len);
}
static void send_remotestop_ack(uint32 gunno,uint8 ret)
{
	 struct t_up_remote_stop_ack ack = {0};
	 memset((uint8 *)&ack,0,sizeof(ack));
	 
	 memcpy(ack.devnum,nwclient.nwparams.devnum,8);
	 ack.gunno = gunno;
	 ack.flag = ret;
	 
	 uint8 data[PRO_MAX_DATA] = {0};
	 uint32 len = 0;
	 probill_remotestop_ack((const struct t_up_remote_stop_ack *)&ack,data,&len);
		
   client_send(data,len);
}
static void send_charge_auth(uint32 gunno,char *cardno,char *password)
{
	struct t_up_authdata authdata;
	memset((uint8 *)&authdata,0,sizeof(authdata));
	
	memcpy(authdata.devnum,nwclient.nwparams.devnum,8);
	authdata.gunno = gunno;
	ASC_to_BCD(authdata.cardno,(uint8 *)cardno,strlen(cardno));
	
	uint8 data[PRO_MAX_DATA] ={0};
  uint32 len = 0;
	 
	probill_chargeauth(&authdata,data,&len);
	
	client_send(data,len);
}
static void send_costmodedown_ack(uint8 gunno,uint8 *costmode_id,uint8 flag)//下发计费模型应答
{
   struct t_up_costmode_ack ack = {0};
   memcpy(ack.devnum,nwclient.nwparams.devnum,8);
   ack.gunno = gunno;
   memcpy(ack.costmode_id,costmode_id,8);
   ack.flag = flag;

   uint8 data[PRO_MAX_DATA] ={0};
   uint32 len = 0;

   probill_costmode_ack(&ack,data,&len);
   client_send(data,len);
}
static void send_keeplive()
{
  uint8 data[PRO_MAX_DATA] ={0};
  uint32 len = 0;

  probill_keeplive_ack(data,&len);
  client_send(data,len);
}

static void send_devyx_ac(uint16 cot,struct t_gunmsg *gunmsg)//上传遥信数据
{
    if(!nwclient.gunmsg)
    {
       return ;
    }
    uint8 data[PRO_MAX_DATA] = {0};
    uint32 len = 0;

    probill_acyx(cot,gunmsg->gunno,&(gunmsg->devyx),data,&len);
    client_send(data,len);
}

static void send_devyc_ac(uint16 cot,struct t_gunmsg *gunmsg)//上传遥测数据
{
    if(!nwclient.gunmsg)
    {
      return ;
    }
    uint8 data[PRO_MAX_DATA] = {0};
    uint32 len = 0;

    probill_acyc_halfword(cot,gunmsg->gunno,&(gunmsg->devyc),data,&len);
    client_send(data,len);
}

static void send_devycmore_ac(uint16 cot,struct t_gunmsg *gunmsg)//上传遥测数据
{
    if(!nwclient.gunmsg)
    {
         return ;
    }
    uint8 data[PRO_MAX_DATA] = {0};
    uint32 len = 0;

    probill_acyc_morehalfword(cot,gunmsg->gunno,&(gunmsg->devycmorehalfword),data,&len);
    client_send(data,len);
}

static void send_chargingdata(uint32 gunno)//上传充电中数据
{  
	 struct t_up_chargingdata chargingdata;
	 memset((uint8 *)&chargingdata,0,sizeof(chargingdata));
	
	 struct t_gunmsg *pgunmsg = nwclient.gunmsg+gunno;
	 
	 if(get_gunstate(pgunmsg) != E_NW_STATE_WORK){
		  return ;
	 }
	 
	 memcpy(chargingdata.devnum,nwclient.nwparams.devnum,8);
	 chargingdata.gunno = gunno;
	 get_order_tradeno(&pgunmsg->order,chargingdata.trade_num);
	 chargingdata.business_type = get_order_business_type(&pgunmsg->order);
	 get_order_userid(&pgunmsg->order,chargingdata.orderno);
	 get_order_cardno(&pgunmsg->order,chargingdata.cardno);
	 get_order_begintime(&pgunmsg->order,chargingdata.begintime);
	 get_order_endtime(&pgunmsg->order,chargingdata.endtime);

	 chargingdata.tip_begin = 0;
	 chargingdata.tip_end = 0;
   chargingdata.peak_begin = 0;
	 chargingdata.peak_end = 0;
	 chargingdata.normal_begin = 0;
 	 chargingdata.normal_end = 0;
	 chargingdata.valley_begin = 0;
   chargingdata.valley_end = 0;
	 
	 chargingdata.tip_power = get_order_time_power(&pgunmsg->order,E_COSTMODE_TIP);
	 chargingdata.peak_power = get_order_time_power(&pgunmsg->order,E_COSTMODE_PEAK);
	 chargingdata.normal_power = get_order_time_power(&pgunmsg->order,E_COSTMODE_NORMAL);
	 chargingdata.valley_power = get_order_time_power(&pgunmsg->order,E_COSTMODE_VALLEY);
	 chargingdata.total_power = get_order_total_power(&pgunmsg->order);
	 chargingdata.tip_eleccost = get_order_time_eleccost(&pgunmsg->order,E_COSTMODE_TIP);
	 chargingdata.peak_eleccost = get_order_time_eleccost(&pgunmsg->order,E_COSTMODE_PEAK);
	 chargingdata.normal_eleccost = get_order_time_eleccost(&pgunmsg->order,E_COSTMODE_NORMAL);
	 chargingdata.valley_eleccost = get_order_time_eleccost(&pgunmsg->order,E_COSTMODE_VALLEY);
	 chargingdata.total_eleccost = get_order_total_eleccost(&pgunmsg->order);
	 chargingdata.total_servercost = get_order_total_servercost(&pgunmsg->order);
	 chargingdata.total_positioncost = get_order_total_positioncost(&pgunmsg->order);
	 chargingdata.cal_type = get_order_caltype(&pgunmsg->order);//计量系数类型 为放电量
	 chargingdata.total_begin = 0;//总起示值
	 chargingdata.total_end = 0;//总止示值
	 chargingdata.timesharing_flag = get_order_sharetime_flag(&pgunmsg->order);//分时计费标识为分时
	 //车辆vin暂时为0int8 vin[17];
	 chargingdata.total_time = get_order_totaltime(&pgunmsg->order);//总耗时
   chargingdata.remain_time =  get_order_remaintime(&pgunmsg->order);//预计剩余充电时间
   chargingdata.total_cost =  get_order_totalcost(&pgunmsg->order);//总费用
	 get_order_orderno(&pgunmsg->order,chargingdata.orderno);
	 
	 
	 uint8 data[PRO_MAX_DATA] = {0};
   uint32 len = 0;

   probill_chargingdata((struct t_up_chargingdata *)&chargingdata,data,&len);
   client_send(data,len);
}
static void sync_charging_record(uint32 gunno)
{
	 struct t_gunmsg *pgunmsg = nwclient.gunmsg+gunno;
	 
	 if(get_gunstate(pgunmsg) != E_NW_STATE_WORK){
		  return ;
	 }
	 struct t_up_chargerecord chargerecord;
	 memset((uint8 *)&chargerecord,0,sizeof(chargerecord));
	 
	 cli_bilrecord_fromorder(gunno,&chargerecord);

   pal_save_current_bill(chargerecord.trade_num,(uint8 *)&chargerecord,sizeof(chargerecord)); 	 
	     
}
static uint8 clipoll_keeplive(struct t_gunmsg *gunmsg)
{
  if(!gunmsg)
  {
       return 1;
  }
  uint32 valuemsec = gunmsg->interval_keeplive *1000;//心跳时间间隔的单位是秒,需要转换成毫秒

  uint32 cnt = valuemsec/TIMER_INTETVAL_MS;

  gunmsg->keeplivecnt = (gunmsg->keeplivecnt+1)%cnt;
  if(0 ==  gunmsg->keeplivecnt)
  {
		if(!gunmsg->keepliverecv)
		{
			gunmsg->keepliverecv = 1 ;
			return 0;
		}
    send_keeplive();
		gunmsg->keepliverecv = 0 ;
  }
	return 1;
}
static void clipoll(struct t_gunmsg *gunmsg)
{
    uint8 retyx = 0;
    uint8 retyc = 0;
    uint8 retycmore = 0;
    
    uint32 cnt = 1000/TIMER_INTETVAL_MS;
    gunmsg->clipoll_cnt  = (gunmsg->clipoll_cnt +1)%cnt;
    if(!gunmsg->clipoll_cnt){//计数1s 同步一下数据  
         retyx = sync_acyx(gunmsg);
         retyc = sync_acyc(gunmsg);
         retycmore = sync_acyc_morehalfword(gunmsg);
		     
			   gunmsg->gun_state.poll(gunmsg);
    }
    if(retyx || retyc)//如果遥信信号有信号量改变 立刻上传遥测遥信数据(突发上传)
    {
      send_devyx_ac(E_CAUSE_SPONT,gunmsg);
      send_devyc_ac(E_CAUSE_SPONT,gunmsg);
      send_devycmore_ac(E_CAUSE_SPONT,gunmsg);
    }
    cnt = (gunmsg->interval_datarep *60*1000)/TIMER_INTETVAL_MS;//定时上班时间间隔单位为分钟
    gunmsg->datarep_cnt =  (gunmsg->datarep_cnt +1)%cnt;
    if(!gunmsg->datarep_cnt)//定时上传
    {
        send_devyx_ac(E_CAUSE_PER,gunmsg);
        send_devyc_ac(E_CAUSE_PER,gunmsg);
        send_devycmore_ac(E_CAUSE_PER,gunmsg);
    }
    cnt = (gunmsg->interval_minrep *1000)/TIMER_INTETVAL_MS;//最小上报时间间隔 单位为秒
    gunmsg->minrep_cnt =  (gunmsg->minrep_cnt +1)%cnt;
    if(!gunmsg->minrep_cnt)//最小间隔时间上传
    {
        if(retycmore)//有功总电度数超过了0.1kwh 或者说是充电中电量变化超过了0.1kwh
        {
            send_devyx_ac(E_CAUSE_SPONT,gunmsg);
            send_devyc_ac(E_CAUSE_SPONT,gunmsg);
            send_devycmore_ac(E_CAUSE_SPONT,gunmsg);
        }
        send_chargingdata(gunmsg->gunno);			 
				sync_charging_record(gunmsg->gunno);
		}
}

static void deal_cmd_reportparaset(uint8 *data,uint32 len)
{
  struct t_down_reportpara_set str;
  pro_getcmd_reportparaset(data,len,(void *)&str);

  struct t_gunmsg *gunmsg = nwclient.gunmsg+str.gunno;
  gunmsg->interval_datarep = str.interval_datarep;
  gunmsg->interval_minrep = str.interval_minrep;
  gunmsg->interval_keeplive = str.interval_keeplive;

	printf("linterval_datarep:%d\r\n",str.interval_datarep);
  printf("interval_minrep:%d\r\n",str.interval_minrep);
  printf("interval_keeplive:%d\r\n",str.interval_keeplive);

  send_deaparaset_ack(str.gunno,0);//应答上报成功
	
  nwclient.devpara_sta = 1;
}
static void dealcmd_charge_auth_ack(uint8 *data,uint32 len)
{
		printf("*****************************************dealcmd_charge_auth_ack*******************************************\r\n");
	  struct t_down_authdata authdata = {0};//充电鉴权下行数据
			
		pro_getcmd_cardauth(data,len,&authdata);
    uint8 startway = E_START_BYCARD;
		if(authdata.authflag){//鉴权失败
			  printf("fail reason = %02x\r\n",authdata.auth_failreason);
			  return ;
		}
	  uint8 failreason;
    uint8 ret = cli_startcharge(authdata.gunno,startway,(void *)&authdata,&failreason);
}
static void dealcmd_chargerecord_ack(uint8 *data,uint32 len)
{
	printf("*****************************************dealcmd_chargerecord_ack*******************************************\r\n");
	struct t_down_chargingrecord_ack ack = {0};
		
	uint8 flag = ack.flag & 0xf0;
	if(!flag){//成功标志位
	 pro_getcmd_chargingrecord(data,len,&ack);
	 pal_save_history_bill(ack.trade_serialnum);
	}
}

static void dealcmd_costmodedown(uint8 *data,uint32 len)
{
   struct  t_guncostmode recvmode;
	 memset((uint8 *)&recvmode,0,sizeof(recvmode));
	
   pro_getcmd_costmode(data, len,&recvmode.head); 

   //qDebug()<<"devnum"<<QByteArray((const char *)str.devnum,8).toHex();
   //qDebug()<<"gunno"<<str.gunno;
   //qDebug()<<"costmode_id"<<QByteArray((const char *)str.costmode_id,8).toHex();
		 
   cp56time2a cpTime;
   transtime(&cpTime,recvmode.head.begintime);
   printf("begintime = %d-%d-%d %d:%d:%d  %d\r\n",cpTime.year,cpTime.month,cpTime.mday,cpTime.hour,cpTime.min,cpTime.msec,cpTime.wday);
   
   transtime(&cpTime,recvmode.head.endtime);
   printf("endtime = %d-%d-%d %d:%d:%d   %d\r\n",cpTime.year,cpTime.month,cpTime.mday,cpTime.hour,cpTime.min,cpTime.msec,cpTime.wday);

   printf("state:%d\r\n",recvmode.head.state);
   printf("caltype:%d\r\n",recvmode.head.caltype);
   printf("timenum:%d\r\n",recvmode.head.timenum);

	 struct t_cli_costmode *pclimode = &((nwclient.gunmsg+recvmode.head.gunno)->guncodemode);
	 if(costmode_isnotequal(pclimode,&recvmode.head)){//不相等
		  printf("costmode is not equal\r\n");
      recvmode.msg = ( struct t_costmodemsg *)os_malloc(sizeof( struct t_costmodemsg)*recvmode.head.timenum);//计费模型信息
      if(!recvmode.msg){
        return ;
      }	
      pro_getcmd_costmodedata(data,len,recvmode.msg,recvmode.head.timenum);
			
			costmode_update(pclimode,&recvmode);
			
      uint32 i = 0;
      for(;i<recvmode.head.timenum;i++){
		    printf("begintime:%d\r\n",(recvmode.msg+i)->begintime);// pos = gethalfword(data,&(msg+i)->begintime,pos);
	    	printf("flag:%d\r\n",(recvmode.msg+i)->flag);//pos = getbyte(data,&(msg+i)->flag,pos);
		    printf("elec_tip:%d\r\n",(recvmode.msg+i)->elec_tip);//pos = getword(data,&(msg+i)->elec_tip,pos);
		    printf("elec_peak:%d\r\n",(recvmode.msg+i)->elec_peak);//pos = getword(data,&(msg+i)->elec_peak,pos);
		    printf("elec_normal:%d\r\n",(recvmode.msg+i)->elec_normal);//pos = getword(data,&(msg+i)->elec_normal,pos);
		    printf("elec_valley:%d\r\n",(recvmode.msg+i)->elec_valley);//pos = getword(data,&(msg+i)->elec_valley,pos);
		    printf("pcs_server:%d\r\n",(recvmode.msg+i)->pcs_server);//pos = getword(data,&(msg+i)->pcs_server,pos);
		    printf("pcs_position:%d\r\n",(recvmode.msg+i)->pcs_position);//pos = getword(data,&(msg+i)->pcs_position,pos);
		    printf("pcs_reserve:%d\r\n",(recvmode.msg+i)->pcs_reserve);//pos = getword(data,&(msg+i)->pcs_reserve,pos);
     }
   }
	 else{
		  printf("costmode is  equal\r\n");
	 }
   send_costmodedown_ack( recvmode.head.gunno,recvmode.head.costmode_id,0);
	 nwclient.costmode_sta = 1;//计费模型下发完成
}
static void dealcmd_remotestart(uint8 *data,uint32 len)
{	
	printf("dealcmd_remotestart\r\n");
	struct t_down_remote_start msg ;
	memset((uint8 *)&msg,0,sizeof(msg));
	
	pro_getcmd_remotestart(data,len, &msg);//获取数据
	
	//初始化订单	
  uint8 failreason = 0;
	uint8 startway = E_START_BYREMOTE;
	
  uint8 ret = cli_startcharge(msg.gunno,startway,(void *)&msg,&failreason);
	
	send_remotestart_ack(msg.gunno,E_START_FLAG_COMFIRE,0); /*第一次收到启动命令发送确认*/
	send_remotestart_ack(msg.gunno,ret,failreason); /*第二次充电成功后返回成功标志*/
}
static void dealcmd_remotestop(uint8 *data,uint32 len)//远程终止
{
	 printf("dealcmd_remotestop\r\n");
	
	 struct t_down_remote_stop msg;
	 pro_getcmd_remotestop(data,len,&msg);
	
	 uint8 ret = cli_stopcharge(msg.gunno,E_END_BY_REMOTE,(uint8 *)&msg);
}
static void dealcmd_remoteupdate(uint8 *data,uint32 len)//远程升级
{
  printf("dealcmd_remoteupdate:");
	for(uint32 i = 0;i<len;i++)
	{ 
		 printf("%02x",*(data+i));
	}
	printf("\r\n");
	
	struct t_down_remote_updatestart updatedata ;
	memset((uint8 *)&updatedata,0,sizeof(updatedata));

	//pro_getcmd_remoteupdate(data,len,&updatedata);//远程启动升级
	
}
static void dealtype_E_TYPE_C_IC_NA_1(uint8 *data,uint32 len)//总召命令
{
    uint16 cot= getcot(data,len);

    if(cot == E_CAUSE_ACT){//运营系统下发总召命令
      nwclient.allcall_sta = 1;
    }
}
static void dealtype_E_TYPE_C_CI_NA_1(uint8 *data,uint32 len)//计数量总召命令
{
   struct t_down_remote_stop//远程终止充电
{
	uint8 devnum[8];
	uint8 gunno;
	uint8 stop[8];
};
}
static void dealtype_E_TYPE_C_CS_NA_1(uint8 *data,uint32 len)//时钟同步命令
{
    uint8 time[7] = {0};
    pro_gettime(data,time);//拿取时间
		pal_callback_timesync(time);//设置时间
	  send_timesync_ack(time);//应答
		
    nwclient.timesyn_sta = 1;//时间同步应答完成		
}

typecmddeal gettcmddeal(uint8 type);//一个声明
static void dealtype_E_TYPE_C_SD_NA_1(uint8 *data,uint32 len)//下发数据项命令
{
   uint8 dataget[PRO_MAX_DATA] = {0};
   memset(dataget,0,sizeof(dataget));

   uint32 lenget = 0;

   uint8 cmd = nw_getprocmd(data,len, dataget,&lenget);

   printf("cmd:%d\r\n",cmd);
   typecmddeal pcmddeal = gettcmddeal(cmd);
   if(pcmddeal){
     (pcmddeal)(dataget,lenget);
   }
}
static void dealtype_E_TYPE_STARTDT_REQ(uint8 *data,uint32 len)//启动数据运输帧
{
  nwclient.startdtack_sta = 1;//启动运输帧待应答
}
static void dealtype_E_TYPE_STOPDT_REQ(uint8 *data,uint32 len)//停止数据运输帧
{

}
static void dealtype_E_TYPE_SIGN_IN_ACK(uint8 *data,uint32 len)//协议标识帧应答
{
  nwclient.proinit_sta = 1;
}
static void dealtype_E_TYPE_LIVE_MSG_ACK(uint8 *data,uint32 len)//心跳包应答
{
   pro_dealkeepliveack();
  (nwclient.gunmsg+0)->keepliverecv = 1;
}
static void cli_deal_netoff(void)
{
	  nwclient.proinit_sta = 0;//是否发送协议标识帧标志位
    nwclient.startdtack_sta = 0;//允许数据传输应答状态
    nwclient.allcall_sta = 0;//总召完成标志位
    nwclient.timesyn_sta = 0;//时间同步状态
	  nwclient.devpara_sta = 0;//设备参数下发状态
    nwclient.costmode_sta = 0;//计费模型下发状态
    nwclient.signin_sta = 0;//签到状态
	
	  pal_callback_set_net_state(E_NW_NETSTATE_OFF);
	  
    nwclient.socketapi->close(nwclient.socket);
	  nwclient.socket = 0;
}

static struct t_typecmddeal typedealbuf[] =
{
   {E_TYPE_C_IC_NA_1,dealtype_E_TYPE_C_IC_NA_1},
   {E_TYPE_C_CI_NA_1,dealtype_E_TYPE_C_CI_NA_1},
   {E_TYPE_C_CS_NA_1,dealtype_E_TYPE_C_CS_NA_1},
   {E_TYPE_C_SD_NA_1,dealtype_E_TYPE_C_SD_NA_1},
   {E_TYPE_STARTDT_REQ,dealtype_E_TYPE_STARTDT_REQ},
   {E_TYPE_STOPDT_REQ,dealtype_E_TYPE_STOPDT_REQ},
   {E_TYPE_SIGN_IN_ACK,dealtype_E_TYPE_SIGN_IN_ACK},
   {E_TYPE_LIVE_MSG_ACK,dealtype_E_TYPE_LIVE_MSG_ACK}
};

static struct t_typecmddeal cmddealbuf[] =
{
    {E_CMD_DOWN_BLACKLIST,},
    {E_CMD_DOWN_CHARGE_AUTH,dealcmd_charge_auth_ack},
    {E_CMD_DOWN_CHARGE_RECORD_CONF,dealcmd_chargerecord_ack},
    {E_CMD_DOWN_CHARGE_SETTLE,},
    {E_CMD_DOWN_RANDOM_NUM,},
    {E_CMD_DOWN_COST_MODE,dealcmd_costmodedown},
    {E_CMD_DOWN_DOUBLE_AUTH_RANDOM_NUM,},
    {E_CMD_DOWN_DOUBLE_AUTH_DATA,},
    {E_CMD_DOWN_ESAM_KEY,},
    {E_CMD_DOWN_ESAM_FIELD1,},
    {E_CMD_DOWN_ESAM_FIELD2,},
    {E_CMD_DOWN_REMOTE_START_CHARGE,dealcmd_remotestart},
    {E_CMD_DOWN_REMOTE_STOP_CHARGE,dealcmd_remotestop},
    {E_CMD_DOWN_REMOTE_POWER_SET,},
    {E_CMD_DOWN_REMOTE_UPDATE,dealcmd_remoteupdate},
    {E_CMD_DOWN_CHARGING_DATA_ACK,},
    {E_CMD_DOWN_DEV_PARA_SET,deal_cmd_reportparaset},
    {E_CMD_DOWN_SM4_KEY_UPDATE,},
    {E_CMD_DOWN_REMOTE_START_CHARGE_RET_ACK,},
    {E_CMD_DOWN_REMOTE_CALL_CHARGERECORD,},
    {E_CMD_DOWN_REMOTE_UPDATE_USERREMAIN,},
    {E_CMD_DOWN_REMOTE_CALL_DEVRTC,},
    {E_CMD_DOWN_VIN_AUTHDATA,},
    {E_CMD_DOWN_REMOTE_CALL_DEVPARA,},
    {E_CMD_DOWN_REMOTE_SET_QRCODE,},
    {E_CMD_DOWN_REMOTE_CALL_DEVCOSTMODE_PARA,},
    {E_CMD_DOWN_REMOTE_CALL_MEDIA_FILE,},
    {E_CMD_DOWN_PLAYCONFIG_DATA,},
    {E_CMD_DOWN_REMOTE_CALL_PALYCONFIG_FILE,},
    {E_CMD_DOWN_REMOTE_CALL_MEDIAPLAY_TOTAL,},
    {E_CMD_DOWN_REMOTE_ENABLE_CONTROL,},
    {E_CMD_DOWN_ALARMINFO,}
};

typecmddeal gettypedeal(uint8 type)
{
   uint32 i = 0;
   uint32 size = sizeof(typedealbuf)/sizeof(struct t_typecmddeal);
   for(i = 0;i<size;i++){
      if(type == typedealbuf[i].type){
         return typedealbuf[i].deal;
      }
   }
   return 0;
}

typecmddeal gettcmddeal(uint8 type)
{
    uint32 i = 0;
    uint32 size = sizeof(cmddealbuf)/sizeof(struct t_typecmddeal);
    for(i = 0;i<size;i++){
       if(type == cmddealbuf[i].type){
          return cmddealbuf[i].deal;
       }
    }
    return 0;
}
#if 0
static void nw_message_handle(void* args)//连接维持任务
{
	//uint8 data[PRO_MAX_DATA] = {0};
	//uint32 recvlen  = 0;
	while(1){
		os_msleep(TIMER_INTETVAL_MS);
    /*
    memset(data,0,sizeof(data));
    recvlen = nwclient.socketapi->recv(nwclient.socket,data,sizeof(data),0); 
    if(recvlen)
    {
      nwpro_pushrecvdata(data,recvlen);
    }
		*/
 }
}
#endif
static void nw_cmd_task(void* args)//信息接收处理
{
	uint8 cmdget;
  uint8 data[PRO_MAX_DATA] = {0};
  uint32 len = 0;
	while(1){		
		os_msleep(TIMER_INTETVAL_MS);
	  memset(data,0,sizeof(data));
		
		if(nwclient.socket <= 0){
      continue ;
    }
    len = nwclient.socketapi->recv(nwclient.socket,data,sizeof(data),0); 
    if(len){
			printf("recvlen = %d\r\n",len);
      nwpro_pushrecvdata(data,len);
    }
    memset(data,0,sizeof(data));
		len = 0;
    uint8 ret = nwpro_getrecvdata(&cmdget,data,&len);
    if(!ret){
			 continue ;
		}
		printf("type:%d\r\n",cmdget);
	  printf("recv>>");
	  for(uint32 i = 0;i<len;i++){
		  printf("%02x",*(data+i));
	  }
	  printf("\r\n");

    typecmddeal pdeal = gettypedeal(cmdget);
    if(pdeal){
      (pdeal)(data,len);//数据包括 帧标识(1个字节) + 可变结构限定词(1个字节) + 传送原因(2个字节) + 应用服务数据单元公共地址(2个字节) +数据(n个字节)
    }
	}
}

static uint8  WAIT_FLAG_SET(uint8 *flag,uint32 ms)
{
	for(uint32 i = 0;i<200*10;i++){
		 os_msleep(TIMER_INTETVAL_MS);
		 if(*flag)
			  return 1;
	}
	return 0; 
}

static void nw_cycle_task(void* args)//用于连接维持相关
{ 
		nwclient.socketapi =  net_get_socket_api();
		while(0 == nwclient.socketapi)
netconnect:	 
		nwclient.socketapi->close(nwclient.socket);
		nwclient.socket = 0;
	  os_msleep(TIMER_INTETVAL_MS);
	  nwclient.socket = nwclient.socketapi->create((const char_t *)nwclient.nwparams.serveip,nwclient.nwparams.port);
		if(nwclient.socket <= 0){
		 
		   goto netconnect;	  
		}
		send_proinit(); //发送协议初始帧
		if(!WAIT_FLAG_SET(&nwclient.proinit_sta,TIMER_INTETVAL_MS)){//等待协议初始化帧回来
			  goto netconnect;	  
		}
		if(!WAIT_FLAG_SET(&nwclient.startdtack_sta,TIMER_INTETVAL_MS)){//等待下发启动运输帧
			 goto netconnect;	
		}
	  send_startdt_req();//应答启动运输帧
		if(!WAIT_FLAG_SET(&nwclient.allcall_sta,TIMER_INTETVAL_MS)){//等待下发总召命令
			goto netconnect;	
		}
		send_allcall_confirm(); // 1 发送总召确认帧
    send_allcallack_1();    // 2 发送type1  响应总召
    send_allcallack_11();   // 2 发送type11  响应总召
    send_allcallack_132();  // 2 发送type132 响应总召
    send_allcall_end();     //3 总召结束
		if(!WAIT_FLAG_SET(&nwclient.timesyn_sta,TIMER_INTETVAL_MS)){//等待时间同步完成
			goto netconnect;	
		}
		if(!WAIT_FLAG_SET(&nwclient.devpara_sta,TIMER_INTETVAL_MS)){//等待设备参数下发完成
			goto netconnect;	
		}
		if(!WAIT_FLAG_SET(&nwclient.costmode_sta,TIMER_INTETVAL_MS)){//等待计费模型下发完成
			goto netconnect;	
		}
		pal_callback_set_net_state(E_NW_NETSTATE_ON);
		
		send_chargerecord(0,E_RECORDFROM_FILE);//上报未上传充电记录	
		while(1){
			uint8 ret = clipoll_keeplive(nwclient.gunmsg);//心跳包轮询
			if(!ret){
				 cli_deal_netoff();
				 goto netconnect;
			}
      uint32 i = 0;
      for(i = 0;i<nwclient.nwparams.gun_cnt;i++){
         clipoll(nwclient.gunmsg+i);
      }			
		  os_msleep(TIMER_INTETVAL_MS);
		}
}

uint32  client_get_net_login_state()
{
	return 0;
}
uint32 client_get_relogin_cnt()
{
   return 0;
}

int pro_client_init()
{
   memset((uint8 *)&nwclient,0,sizeof(nwclient));
	
	 nwpro_mutex = os_mutex_create();
	
   nw_param_init(&nwclient.nwparams);
	
   nwclient.gunmsg = (struct t_gunmsg *)os_malloc(nwclient.nwparams.gun_cnt *sizeof(struct t_gunmsg));//枪的一些信息
	
	
   gunmsg_init(nwclient.gunmsg,nwclient.nwparams.gun_cnt);//枪信息的初始化

	 pal_init();
	 os_pthread_t client_thread;
   os_pthread_t incident_thread;
   //os_pthread_t message_thread;

   if (os_pthread_create("nwsdk_cycle", &client_thread, nw_cycle_task, NULL, OS_TASK_PRIO_NOMAL, OS_STACK_SIZE_SUPER_LARGE*2) != 0) {
        return -1;
   }
   if(os_pthread_create("nwsdk_cmddeal", &incident_thread, nw_cmd_task, NULL, OS_TASK_PRIO_NOMAL, OS_STACK_SIZE_SUPER_LARGE*2) != 0) {//这个任务主要是处理接收的信息的
        return -1;
   }
	
	 /*
   if(os_pthread_create("nwsdk_work", &message_thread, nw_message_handle, NULL, OS_TASK_PRIO_NOMAL, OS_STACK_SIZE_SUPER_LARGE*2) != 0) {
        return -1;
   }
	 */
   return 0;
}

int32_t nw_send_touch_card_start_charge(uint32_t gunnum, char_t *id, char_t *pwd, uint8_t type, uint32_t value)
{
	printf("nw_send_touch_card_start_charge gunnum:%d id:%s pwd:%s type:%d value:%d\r\n", gunnum,id,pwd,type,value);
	send_charge_auth(gunnum-1,id,pwd);
	return 0;
}
int32_t nw_send_touch_charge_idle(uint32_t gun_cnt)
{
	 printf("nw_send_touch_charge_idle \r\n");
    return 0;
}
int32_t nw_send_touch_charge_stoped(uint32_t gun_cnt, const char_t *stop_reason)
{
	printf("nw_send_touch_charge_stoped :%s\r\n",stop_reason);
	uint32 tmpgunno = gun_cnt-1;
	
	uint32 reason = E_END_BY_OTHER;
	 
	if(strcmp("1000",stop_reason) == 0){//自动结束
		 reason = E_END_BY_AUTO;
	}else if(strcmp("1008",stop_reason) == 0){//刷卡结束
		 reason = E_END_BY_SWIPCARD;
	}else if(strcmp("100A",stop_reason) == 0){//BMS故障结束
		 reason = E_END_BY_BMS_ALARM;
	}else if(strcmp("3003",stop_reason) == 0){//急停按钮结束
		 reason = E_END_BY_STOPBUTTON;
	}else if(strcmp("100D",stop_reason) == 0){//拔枪结束
		 reason = E_END_BY_GUNM;
	}else if(strcmp("1009",stop_reason) == 0){//失流
	   reason = E_END_BY_LOWCURRENT;
	}else if(strcmp("1003",stop_reason) == 0){//屏幕停止
		 reason = E_END_BY_GUI;
	} 
  cli_stopcharge(tmpgunno,reason,0);//结束充电
    return 0;
}
int32_t nw_send_touch_error_occured(uint32_t gun_cnt, const char_t* err_no)
{
	printf("nw_send_touch_error_occured gunno:%d err:%s\r\n",gun_cnt,err_no);
	uint32 tmpgun = gun_cnt - 1;
  struct t_pal_alarm *alarm = &((nwclient.gunmsg+tmpgun)->alarmmsg);
	
	add_alarm(alarm,(uint8 *)err_no);
	print_alarm(alarm);
	
	return 0;
}
int32_t nw_send_touch_error_recovered(uint32_t gun_cnt, const char_t* err_no)
{
	printf("nw_send_touch_error_recovered gunno:%d err:%s\r\n",gun_cnt,err_no);
	uint32 tmpgun = gun_cnt -1;
  struct t_pal_alarm *alarm = &(nwclient.gunmsg+tmpgun)->alarmmsg;
	
	detele_alarm(alarm,(uint8 *)err_no);
	print_alarm(alarm);
	
  return 0 ;
}
int32_t nw_touch_set_equipment_id(uint8_t* ID_str)
{
	return 0;
}
int32_t nw_touch_set_mac_addr(uint8_t* mac_str)
{
	return 0;
}
int32_t nw_charger_state_reup(uint32_t gun_id)
{
     return 0;
}
